// 导入相关的模块
const express = require("express");
const md5 = require("md5");
const mongoose = require("mongoose");
const jsonwebtoken = require("jsonwebtoken");
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");
const fs = require("fs");
const e = require("express");

// 读取secret
const secret = fs.readFileSync(path.join(__dirname, "../", ".env"), "utf-8");
// 产生web实例
const app = express();
// mogoose的使用（1连接数据库，2产生schema对象，3产生模型，4调用具体方法）
// 1连接数据库
mongoose.connect("mongodb://127.0.0.1:27017/houniaolvxing", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});
// 2产生schema对象
const usersSchema = new mongoose.Schema({
    phone: {
        type: String,
        required: true,
    },
    mail: {
        type: String,
        required: true,
    },
    password: {
        type: String,
        required: true,
    },
    img: String,
    gender: String,
    value: String,
});
// 3产生模型
// 第三参数为可选参数，表示model操作的表/集合名。如果不写第三个参数，则默认为第一参数小写的复数形式
const Model = mongoose.model("User", usersSchema, "users");


// 中间件的使用
// 解析表单数据
app.use(bodyParser.urlencoded({
    extended: false
}));
// 解析json数据
app.use(bodyParser.json());
// 解决跨域
app.use(cors());

// // 密码加密中间件
const passwdCrypt = (req, res, next) => {
    // 明文密码字段为password
    // 加盐加密或加料加密
    const passwd = md5(req.body.password + md5(req.body.password).substr(9, 17));
    // 将加密的密码挂载到req的body上（覆盖原密码）
    req.body.password = passwd;
    // 继续
    next();
};

// 路由

// 接口1：用户注册
app.post("/my/register", passwdCrypt, (req, res) => {
    let {
        phone,
        mail,
        password
    } = req.body
    // 对数据进行校验（空值，邮箱格式，长度等）
    if (!phone || !mail || !password) {
        return res.send({
            err: -1,
            msg: '参数错误'
        })
    }
    if (!/^1[3456789]\d{9}$/.test(phone)) {
        return res.send({
            err: -2,
            msg: '请输入11位手机号码'
        })
    }
    if (!/^[A-Za-z]\w{5,17}@(163\.com|126\.com|yeach\.net)$/.test(mail)) {
        return res.send({
            err: -163,
            msg: '首字母开头、5-17位，网易邮箱，126邮箱'
        })
    }
    // 查询数据库，当前账号是否已注册
    Model.find({
            phone
        })
        .then((data) => {
            if (data.length > 0) {
                res.send({
                    err: -3,
                    msg: '手机号已注册'
                })
            } else {
                // 可以注册（插入数据）
                return Model.insertMany({
                    phone,
                    mail,
                    password,
                    gender: "1",
                    value: "",
                    img: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0H320120Z3%2F200H3120Z3-6-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1623553347&t=8755c0b849d2f1f295b934f76b0380c7"

                })
            }
        })
        .then((data) => {

            if (data.length > 0) {
                res.send({
                    err: 0,
                    msg: '注册成功'
                })
            } else {
                res.send({
                    err: -4,
                    msg: '注册失败'
                })
            }
        })
        .catch((err) => {
            res.send({
                err: -5,
                msg: '状态异常，请重试'
            })
        })
});


// 接口2：用户登录
app.post("/my/login", passwdCrypt, (req, res) => {
    // 获取手机号与加密之后的密码
    let data = req.body;
    // 去数据库中去查询上是否存在对应的记录
    // 注意：mongoose提供的方法都是异步的
    Model.findOne(data).then((ret) => {
        // findOne：查不到返回null，查到就返回对应的文档（建议）
        // find：查不到返回空数组，查到了返回包括文档的数组
        if (ret) {
            // 查到了，签发令牌
            // 语法：jsonwebtoken.sign(载荷对象,secret)
            let _token = jsonwebtoken.sign({
                    phone: ret.phone,
                },secret);
            res.send({
                err: 0,
                msg: "登录成功！",
                _token,
                // _token: "zhangsan " + _token,
            });
        } else {
            // 没查到
            res.send({
                err: 1,
                msg: "手机号或密码错误。",
            });
        }
    });
});

// 接口3：获取用户信息
app.get("/my/getUserInfo", (req, res) => {
    // 1. 认证token（在认证的过程中，如果认证失败，程序会抛异常）
    try {
        let tokenStr = req.headers["authorization"];
        let arr = tokenStr.split(" ");
        // 最后一个元素即token
        let token = arr[arr.length - 1];
        // 开始验证令牌
        // 语法：jsonwebtoken.verify(令牌字符串,secret)
        // 验证成功返回载荷，验证失败抛异常
        const ret = jsonwebtoken.verify(token, secret);
        // （可选）验证是否过期【约定过期时间2小时，7200s】
        if (Date.now() / 1000 - ret.iat > 7200) {
            // 过期了
            res.send({
                err: 3,
                msg: "token令牌已经过期。",
                _token: "",
            });
        } else {
            // 没过期
            // 判断是否马上要过期了，如果是自动给它生成新的token
            if (Date.now() / 1000 - ret.iat > 5400) {
                token = jsonwebtoken.sign({
                        phone: ret.phone,
                    },
                    secret
                );
            }
            // 获取数据
            Model.findOne({
                phone: ret.phone
            }).then((ret) => {
                // 2. 返回（失败或成功）
                if (ret) {
                    // 取到信息了，则返回
                    res.send({
                        err: 0,
                        msg: "用户信息获取成功！",
                        _token: token,
                        data: {
                            phone: ret.phone.replace(/(\d{3})\d{4}(\d{4})$/, "$1****$2"),
                            // phone: ret.phone,
                            mail: ret.mail,
                            img: ret.img,
                            gender: ret.gender,
                            value: ret.value,
                            img: ret.img
                        },
                    });
                } else {
                    // 账号已经已经没了
                    res.send({
                        err: 4,
                        msg: "你号没了。",
                        _token: "",
                    });
                }
            });
        }
    } catch (error) {
        // 抛异常了
        res.status(500).send({
            error: 2,
            msg: "token令牌验证失败。",
        });
    }
});

// 更新数据
app.post("/my/settingup", passwdCrypt, (req, res) => {
    let {
        mail,
        password,
        gender,
        value,
    } = req.body
    let tokenStr = req.headers["authorization"];
    let arr = tokenStr.split(" ");
    // 最后一个元素即token
    let token = arr[arr.length - 1];
    // 开始验证令牌
    // 语法：jsonwebtoken.verify(令牌字符串,secret)
    // 验证成功返回载荷，验证失败抛异常
    const ret = jsonwebtoken.verify(token, secret);
    let phone = ret.phone
    // 查询数据库，当前账号是否已注册
    Model.updateOne({
            phone
        }, {
            $set: {
                mail,
                password,
                gender,
                value,
            }
        })
        .then((data) => {
            res.send({
                err: 0,
                msg: '修改成功'
            })
        })
        .catch((err) => {
            res.send({
                err: -1,
                msg: '修改失败'
            })
        })
});
// ------------------------------------定制订单------------------------------------------
const orderSchema = new mongoose.Schema({
    phone: {
        type: String,
        required: true,
    },
    daren: {
        type: String,
        required: true,
    },
    ertong: {
        type: String,
        required: true,
    },
    departure: {
        type: String,
        required: true,
    },
    region: {
        type: String,
        required: true,
    },
    linkman: {
        type: String,
        required: true,
    },
    cell: {
        type: String,
        required: true,
    },
    weixin: {
        type: String,
        required: true,
    },
    arrive: {
        type: String,
        required: true,
    },
    travel: {
        type: String,
        required: true,
    },
    rests: String,
});
// 3产生模型
// 第三参数为可选参数，表示model操作的表/集合名。如果不写第三个参数，则默认为第一参数小写的复数形式
const order = mongoose.model("order", orderSchema, "orders");
// 注册
app.post("/my/order", (req, res) => {
    let {
        daren,
        ertong,
        linkman,
        cell,
        weixin,
        arrive,
        travel,
        rests,
        region,
        departure
    } = req.body
    // 对数据进行校验（空值，邮箱格式，长度等）
    if (!daren || !ertong || !linkman || !cell || !weixin || !arrive || !travel || !region || !departure) {
        return res.send({
            err: -1,
            msg: '参数错误'
        })
    }
    let tokenStr = req.headers["authorization"];
    let arr = tokenStr.split(" ");
    // 最后一个元素即token
    let token = arr[arr.length - 1];
    // 开始验证令牌
    // 语法：jsonwebtoken.verify(令牌字符串,secret)
    // 验证成功返回载荷，验证失败抛异常
    const ret = jsonwebtoken.verify(token, secret);
    let phone = ret.phone
    // 查询数据库，当前账号是否已注册
    order.insertMany({
            phone,
            daren,
            ertong,
            linkman,
            cell,
            weixin,
            arrive,
            travel,
            rests,
            region,
            departure
        })
        .then((data) => {
            if (data.length > 0) {
                res.send({
                    err: 1,
                    msg: '定制成功'
                })
            } else {
                res.send({
                    err: -2,
                    msg: '定制失败'
                })
            }
        })
        .catch((err) => {
            res.send({
                err: -5,
                msg: '状态异常，请重试1'
            })
        })
});
// 查询
app.get("/my/userorder", (req, res) => {
    // 1. 认证token（在认证的过程中，如果认证失败，程序会抛异常）
    try {
        let tokenStr = req.headers["authorization"];
        let arr = tokenStr.split(" ");
        // 最后一个元素即token
        let token = arr[arr.length - 1];
        // 开始验证令牌
        // 语法：jsonwebtoken.verify(令牌字符串,secret)
        // 验证成功返回载荷，验证失败抛异常
        const ret = jsonwebtoken.verify(token, secret);
        // （可选）验证是否过期【约定过期时间2小时，7200s】
        if (Date.now() / 1000 - ret.iat > 7200) {
            // 过期了
            res.send({
                err: 3,
                msg: "token令牌已经过期。",
                _token: "",
            });
        } else {
            // 没过期
            // 判断是否马上要过期了，如果是自动给它生成新的token
            if (Date.now() / 1000 - ret.iat > 5400) {
                token = jsonwebtoken.sign({
                        phone: ret.phone,
                    },
                    secret
                );
            }
            // 获取数据
            order.findOne({
                phone: ret.phone
            }).then((ret) => {
                // 2. 返回（失败或成功）
                if (ret) {
                    // 取到信息了，则返回
                    res.send({
                        err: 0,
                        msg: "用户信息获取成功！",
                        _token: token,
                        data: {
                            phone: ret.phone,
                            daren: ret.daren,
                            ertong: ret.ertong,
                            linkman: ret.linkman,
                            cell: ret.cell,
                            weixin: ret.weixin,
                            arrive: ret.arrive,
                            travel: ret.travel,
                            rests: ret.rests,
                            region: ret.region,
                            departure: ret.departure
                        },
                    });
                } else {
                    // 账号已经已经没了
                    res.send({
                        err: 4,
                        msg: "你号没了。",
                        _token: "",
                    });
                }
            });
        }
    } catch (error) {
        // 抛异常了
        res.status(500).send({
            error: 2,
            msg: "token令牌验证失败。",
        });
    }
});
// 更新
app.post("/my/genxin", (req, res) => {
    let {
        daren,
        ertong,
        linkman,
        cell,
        weixin,
        arrive,
        travel,
        rests,
        region,
        departure
    } = req.body
    let tokenStr = req.headers["authorization"];
    let arr = tokenStr.split(" ");
    // 最后一个元素即token
    let token = arr[arr.length - 1];
    // 开始验证令牌
    // 语法：jsonwebtoken.verify(令牌字符串,secret)
    // 验证成功返回载荷，验证失败抛异常
    const ret = jsonwebtoken.verify(token, secret);
    let phone = ret.phone
    // 查询数据库，当前账号是否已注册
    order.updateOne({
            phone
        }, {
            $set: {
                daren,
                ertong,
                linkman,
                cell,
                weixin,
                arrive,
                travel,
                rests,
                region,
                departure
            }
        })
        .then((data) => {
            res.send({
                err: 0,
                msg: '修改成功'
            })
        })
        .catch((err) => {
            res.send({
                err: -1,
                msg: '修改失败'
            })
        })
});


// 监听8000
app.listen(8000, () => {
    console.log("server is running at http://127.0.0.1:8000");
});